package com.calvin.study.completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Supplier;

import org.apache.commons.lang3.StringUtils;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.thread.ThreadUtil;

//两个任务组合任务测试（都得完成）
public class CombinationAllTaskTest extends BaseThreadPoolExecutor {
	
	static CompletableFuture<String> future1 = CompletableFuture.supplyAsync(new Supplier<String>() {
		@Override
		public String get() {
			System.out.println("异步任务1，创建订单");
			return "orderid" + new Snowflake().nextIdStr();
		}
	}, executor);

	static CompletableFuture<String> future2 = CompletableFuture.supplyAsync(new Supplier<String>() {
		@Override
		public String get() {
			System.out.println("异步任务2，订单付款");
			return "payid" + new Snowflake().nextIdStr();
		}
	}, executor);
	
	
	//必须等待future1、future2执行完毕后，调用该函数（有返回结果）
	public static void thenCombine() throws InterruptedException, ExecutionException {
		CompletableFuture<String> future3 = future1.thenCombineAsync(future2, new BiFunction<String,String,String>() {

			@Override
			public String apply(String res1, String res2) {
				if(StringUtils.isNotBlank(res1)) {
					System.out.println("任务3，订单日志 orderid: "+res1);
				}
				
				if(StringUtils.isNotBlank(res2)) {
					System.out.println("任务3，支付日志 payid: "+res2);
				}
				return "任务3完成";
			}
			
		}, executor);
		System.out.println(future3.get());
	}
	
	
	//必须等待future1、future2执行完毕后，调用该函数（无返回结果）
	public static void thenAcceptBothTest() {
		future1.thenAcceptBothAsync(future2, new BiConsumer<String, String>() {
			@Override
			public void accept(String res1, String res2) {
				System.out.println("任务1返回值：" + res1);
				System.out.println("任务2返回值：" + res2);
			}
		}, executor);
	}
	
	
	//1.无法获取两个任务的返回结果
	//2.任务3的无处理结果返回
	//3.任务1和任务2中任何一方法发生异常，任务3无法执行。
	public static void runAfterBothTest() {
		
		future1.runAfterBothAsync(future2, ()->{
			System.out.println("任务3，给用户增加积分");
		}, executor);
	}
	
	
	public static void main(String[] args) {
		
		try {
			//thenCombine();
			//thenAcceptBothTest();
			runAfterBothTest();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
